//UsrAI.h
#ifndef USRAI_H
#define USRAI_H

#include "AI.h"
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <ctime>
#include <unordered_set>
#include <string>
#include <queue>

extern tagGame tagUsrGame;
extern ins UsrIns;

#ifndef MAPPATTERN_SHALLOWS
#define MAPPATTERN_SHALLOWS 3
#endif

class UsrAI : public AI
{
public:
    enum GameStage {
        STAGE_INITIAL,
        STAGE_BUILD_HOUSES,
        STAGE_POPULATION_GROWTH,
        STAGE_COLLECT_RESOURCES,
        STAGE_BUILD_REQUIRED_BUILDINGS,
        STAGE_UPGRADE_AGE,
        STAGE_BUILD_FISHING_BOAT
    };
    static bool villagersAssigned;

    static tagInfo prevInfo;
    static int center_x, center_y;
    static bool centerInitialized;
    static std::set<std::pair<int, int>> occupiedPositions;

    static int houseCount;
    static int housesUnderConstruction;
    static const int TARGET_HOUSES = 4;
    static GameStage currentStage;
    static int searchRadius;
    static int lastHouseX, lastHouseY;
    static int houseBuilderSN;

    static int targetPopulation;
    static time_t lastVillagerProductionTime;
    static bool buildingHousesInProgressInPopulationStage;

    static bool stockBuilt;
    static bool dockBuilt;
    static bool fishingBoatBuilt;
    static bool ageUpgraded;
    static int dockBuilderSN;
    static bool dockBuilderReserved;
    static bool dockConstructionStarted;
    static int totalDocksPresent;
    static int completedDocksCount;
    static const int TARGET_DOCKS_NUM = 2;

    static int fishingBoatCount;
    static const int TARGET_FISHING_BOATS = 4;
    static const int TARGET_BOATS_PER_DOCK = 2;
    static std::map<int, int> dockFishingBoatCount;

    static int foundDockX;
    static int foundDockY;
    static bool dockPositionFound;

    static std::vector<std::pair<int, int>> fishPositions;
    static bool fishPositionsInitialized;
    static std::unordered_set<int> ordinaryVillagers;

    UsrAI(){this->id=0;}
    ~UsrAI(){}

private:
    bool isLand(int type);
    bool isOcean(int type);
    bool isMapCellLand(int x, int y, const tagInfo& info);
    bool isCellAdjacentToLand(int cx, int cy, const tagInfo& info);
    bool isPositionReachable(int x, int y, const tagInfo& info);

    bool isTooCloseToExistingDocks(int newDockX, int newDockY, const tagInfo& info);

    bool isPositionValidForBuilding(int x, int y, int width, int height, int buildingType, const tagInfo& info);
    bool isPositionValidForHouse(int x, int y, const tagInfo& info);

    bool findCoastalPositionNearCenter(int& x, int& y, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions);
    bool findDockPositionNearFish(int& x, int& y, const std::pair<int, int>& targetFishPos, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions);

    bool isDockNearFish(const std::pair<int, int>& fishPos, const tagInfo& info);

    void assignTasksToVillagersWithLimits(const tagInfo& info, bool reserveOneIdleForDock);
    void processData() override;

    tagInfo getInfo(){return tagUsrGame.getInfo();}

    int AddToIns(instruction ins) override
    {
        UsrIns.lock.lock();
        ins.id=UsrIns.g_id;
        UsrIns.g_id++;
        UsrIns.instructions.push(ins);
        UsrIns.lock.unlock();
        return ins.id;
    }

    void clearInsRet() override
    {
        tagUsrGame.clearInsRet();
    }
    void assignTasksToVillagers(const tagInfo& info);
    int findNearestResource(const tagFarmer& farmer, int resourceType, const tagInfo& info, const std::unordered_set<int>& excludedSNs);
    void initializeCenter(const tagInfo& info);

    void buildHousesPhase(const tagInfo& info);
    bool findNearbyPosition(int& x, int& y, const tagInfo& info);

    void populationGrowthPhase(const tagInfo& info);
    void produceVillagers(const tagInfo& info);

    void collectResourcesPhase(const tagInfo& info);

    void buildRequiredBuildingsPhase(const tagInfo& info);
    void upgradeAgePhase(const tagInfo& info);
    void buildFishingBoatPhase(const tagInfo& info);

    void initializeFishPositions(const tagInfo& info);

    void assignFishingBoatsToFishResources(const tagInfo& info);
};

#endif

//UsrAI.cpp
#include "UsrAI.h"
#include <iostream>
#include <algorithm>
#include <ctime>
#include <sstream>
#include <unordered_set>
#include <string>
#include <climits>
#include <cmath>
#include <vector>

#define ACTION_OK 0


using namespace std;


tagGame tagUsrGame;
ins UsrIns;
tagInfo UsrAI::prevInfo;
int UsrAI::center_x = 0;
int UsrAI::center_y = 0;
bool UsrAI::centerInitialized = false;
set<pair<int, int>> UsrAI::occupiedPositions;
int UsrAI::houseCount = 0;
int UsrAI::housesUnderConstruction = 0;
UsrAI::GameStage UsrAI::currentStage = UsrAI::STAGE_INITIAL;
int UsrAI::searchRadius = 1;
int UsrAI::lastHouseX = -1;
int UsrAI::lastHouseY = -1;
int UsrAI::houseBuilderSN = -1;


int UsrAI::targetPopulation = 0;
time_t UsrAI::lastVillagerProductionTime = time(nullptr);
bool UsrAI::buildingHousesInProgressInPopulationStage = false;


bool UsrAI::stockBuilt = false;
bool UsrAI::dockBuilt = false;
bool UsrAI::fishingBoatBuilt = false;
bool UsrAI::ageUpgraded = false;
bool UsrAI::villagersAssigned = false;
int UsrAI::dockBuilderSN = -1;
bool UsrAI::dockBuilderReserved = false;
bool UsrAI::dockConstructionStarted = false;
int UsrAI::totalDocksPresent = 0;
int UsrAI::completedDocksCount = 0;

int UsrAI::fishingBoatCount = 0;
std::map<int, int> UsrAI::dockFishingBoatCount;


int UsrAI::foundDockX = -1;
int UsrAI::foundDockY = -1;
bool UsrAI::dockPositionFound = false;


std::vector<std::pair<int, int>> UsrAI::fishPositions;
bool UsrAI::fishPositionsInitialized = false;
std::unordered_set<int> UsrAI::ordinaryVillagers;

const int MAX_HOUSE_SEARCH_RADIUS = 15;

bool UsrAI::isLand(int type) {
    return type == MAPPATTERN_GRASS || type == MAPPATTERN_SHALLOWS;
}

bool UsrAI::isOcean(int type) {
    return type == MAPPATTERN_OCEAN;
}

bool UsrAI::isMapCellLand(int x, int y, const tagInfo& info) {
    if (x < 0 || y < 0 || x >= 128 || y >= 128) {
        return false;
    }
    return this->isLand((*info.theMap)[x][y].type);
}

bool UsrAI::isCellAdjacentToLand(int cx, int cy, const tagInfo& info) {
    const int offsets[4][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1}
    };
    for (const auto& offset : offsets) {
        int adjX = cx + offset[0];
        int adjY = cy + offset[1];
        if (this->isMapCellLand(adjX, adjY, info)) {
            return true;
        }
    }
    return false;
}

bool UsrAI::isPositionReachable(int x, int y, const tagInfo& info) {
    const int offsets[8][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
    };

    for (const auto& offset : offsets) {
        int checkX = x + offset[0];
        int checkY = y + offset[1];

        if (checkX >= 0 && checkY >= 0 && checkX < 128 && checkY < 128) {
            if (this->isLand((*info.theMap)[checkX][checkY].type) &&
                !occupiedPositions.count({checkX, checkY})) {
                return true;
            }
        }
    }
    return false;
}


bool UsrAI::isTooCloseToExistingDocks(int newDockX, int newDockY, const tagInfo& info) {
    const int MIN_SEPARATION_BUFFER = 1;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK) {
            int existingDockX = b.BlockDR;
            int existingDockY = b.BlockUR;

            int exclusionMinX = existingDockX - MIN_SEPARATION_BUFFER;
            int exclusionMaxX = existingDockX + 2 - 1 + MIN_SEPARATION_BUFFER;
            int exclusionMinY = existingDockY - MIN_SEPARATION_BUFFER;
            int exclusionMaxY = existingDockY + 2 - 1 + MIN_SEPARATION_BUFFER;

            bool x_overlap = (newDockX <= exclusionMaxX) && (newDockX + 2 - 1 >= exclusionMinX);
            bool y_overlap = (newDockY <= exclusionMaxY) && (newDockY + 2 - 1 >= exclusionMinY);

            if (x_overlap && y_overlap) {
                this->DebugText("  候选船坞位置 (" + to_string(newDockX) + "," + to_string(newDockY) + ") 距离现有船坞 (" + to_string(existingDockX) + "," + to_string(existingDockY) + ") 过近。排除区域: X[" + to_string(exclusionMinX) + "," + to_string(exclusionMaxX) + "] Y[" + to_string(exclusionMinY) + "," + to_string(exclusionMaxY) + "]");
                return true;
            }
        }
    }
    return false;
}


void UsrAI::initializeCenter(const tagInfo& info) {
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_CENTER) {
            center_x = building.BlockDR;
            center_y = building.BlockUR;
            centerInitialized = true;
            this->DebugText("市政中心位于 (" + to_string(center_x) + "," + to_string(center_y) + ")");

            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    occupiedPositions.insert({center_x + i, center_y + j});
                }
            }

            currentStage = STAGE_BUILD_HOUSES;
            this->DebugText("=== 进入建造房屋阶段 ===");

            if (!dockPositionFound) {
                std::set<std::pair<int, int>> tempExcludedPositions;
                if (!fishPositionsInitialized) {
                    this->initializeFishPositions(info);
                }
                if (!fishPositions.empty() && this->findDockPositionNearFish(foundDockX, foundDockY, fishPositions[0], info, tempExcludedPositions)) {
                    dockPositionFound = true;
                    this->DebugText("初始船坞位置搜索成功: 存储在 (" + to_string(foundDockX) + "," + to_string(foundDockY) + ")");
                } else {
                    this->DebugText("初始船坞位置搜索失败，稍后重试");
                }
            }

            if (!info.farmers.empty()) {
                houseBuilderSN = info.farmers[0].SN;
                this->DebugText("指派村民 #" + to_string(houseBuilderSN) + " 为房屋建造者。");

                for (size_t i = 0; i < info.farmers.size(); i++) {
                    if (info.farmers[i].SN != houseBuilderSN) {
                        ordinaryVillagers.insert(info.farmers[i].SN);
                        this->DebugText("村民 #" + to_string(info.farmers[i].SN) + " 已添加到普通村民集合。");
                    }
                }
            }
            break;
        }
    }
}

bool UsrAI::isPositionValidForBuilding(int x, int y, int width, int height, int buildingType, const tagInfo& info) {
    int firstHeight = -2;

    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            int checkX = x + i;
            int checkY = y + j;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) {
                this->DebugText("  位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 超出地图边界。");
                return false;
            }

            if (buildingType != BUILDING_DOCK) {
                if (!this->isLand((*info.theMap)[checkX][checkY].type) || (*info.theMap)[checkX][checkY].height == -1) {
                    this->DebugText("  位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 不是有效陆地或坡地，不适用于非船坞建筑。");
                    return false;
                }
                if (firstHeight == -2) {
                    firstHeight = (*info.theMap)[checkX][checkY].height;
                } else if ((*info.theMap)[checkX][checkY].height != firstHeight) {
                    this->DebugText("  位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 高度不一致，不适用于非船坞建筑。");
                    return false;
                }
            }

            if (occupiedPositions.count({checkX, checkY})) {
                this->DebugText("  位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 已被计划中的建筑占用。");
                return false;
            }

            for (const auto& b : info.buildings) {
                int b_width, b_height;
                if (b.Type == BUILDING_DOCK) { b_width = 2; b_height = 2; }
                else if (b.Type == BUILDING_STOCK || b.Type == BUILDING_CENTER || b.Type == BUILDING_GRANARY || b.Type == BUILDING_ARMYCAMP || b.Type == BUILDING_MARKET || b.Type == BUILDING_FARM || b.Type == BUILDING_RANGE || b.Type == BUILDING_STABLE) { b_width = 3; b_height = 3; }
                else if (b.Type == BUILDING_HOME || b.Type == BUILDING_ARROWTOWER) { b_width = 2; b_height = 2; }
                else { b_width = 1; b_height = 1; }

                if (checkX >= b.BlockDR && checkX < (b.BlockDR + b_width) &&
                    checkY >= b.BlockUR && checkY < (b.BlockUR + b_height)) {
                    this->DebugText("  位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 与现有建筑 SN " + to_string(b.SN) + " 类型 " + to_string(b.Type) + " 位于 (" + to_string(b.BlockDR) + "," + to_string(b.BlockUR) + ") 重叠。");
                    return false;
                }
            }

            for (const auto& res : info.resources) {
                if (res.BlockDR == checkX && res.BlockUR == checkY) {
                    this->DebugText("  位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 与资源 SN " + to_string(res.SN) + " 类型 " + to_string(res.Type) + " 重叠。");
                    return false;
                }
            }
        }
    }

    if (buildingType == BUILDING_DOCK) {
        if (width != 2 || height != 2) {
            this->DebugText("  船坞必须是 2x2，但请求的宽度/高度是 " + to_string(width) + "x" + to_string(height) + "。");
            return false;
        }

        if (!(this->isOcean((*info.theMap)[x][y].type) &&
              this->isOcean((*info.theMap)[x + 1][y].type) &&
              this->isOcean((*info.theMap)[x][y + 1].type) &&
              this->isOcean((*info.theMap)[x + 1][y + 1].type))) {
            this->DebugText("  船坞在 (" + to_string(x) + "," + to_string(y) + ") 的 2x2 区域并非全部为海洋。");
            return false;
        }

        bool hasDirectLandAdjacency = false;
        if ((x - 1 >= 0 && this->isLand((*info.theMap)[x - 1][y].type)) ||
            (x - 1 >= 0 && y + 1 < 128 && this->isLand((*info.theMap)[x - 1][y + 1].type))) {
            hasDirectLandAdjacency = true;
        }
        if (!hasDirectLandAdjacency && ((x + 2 < 128 && this->isLand((*info.theMap)[x + 2][y].type)) ||
                                        (x + 2 < 128 && y + 1 < 128 && this->isLand((*info.theMap)[x + 2][y + 1].type)))) {
            hasDirectLandAdjacency = true;
        }
        if (!hasDirectLandAdjacency && ((y - 1 >= 0 && this->isLand((*info.theMap)[x][y - 1].type)) ||
                                        (y - 1 >= 0 && x + 1 < 128 && this->isLand((*info.theMap)[x + 1][y - 1].type)))) {
            hasDirectLandAdjacency = true;
        }
        if (!hasDirectLandAdjacency && ((y + 2 < 128 && this->isLand((*info.theMap)[x][y + 2].type)) ||
                                        (y + 2 < 128 && x + 1 < 128 && this->isLand((*info.theMap)[x + 1][y + 2].type)))) {
            hasDirectLandAdjacency = true;
        }

        if (!hasDirectLandAdjacency) {
            this->DebugText("船坞位置 (" + to_string(x) + "," + to_string(y) + ") 的任何一边都没有直接与陆地相邻。");
            return false;
        }

        int landAdjacentCorners = 0;
        std::pair<int, int> cornerCells[4] = {
            {x, y},
            {x + 1, y},
            {x, y + 1},
            {x + 1, y + 1}
        };

        for (const auto& corner : cornerCells) {
            if (this->isCellAdjacentToLand(corner.first, corner.second, info)) {
                landAdjacentCorners++;
            }
        }

        if (landAdjacentCorners < 2) {
            this->DebugText("船坞在 (" + to_string(x) + "," + to_string(y) + ") 只有 " + to_string(landAdjacentCorners) + " 个角与陆地相邻。至少需要 2 个。");
            return false;
        }
    }

    return true;
}

bool UsrAI::isPositionValidForHouse(int x, int y, const tagInfo& info) {
    return this->isPositionValidForBuilding(x, y, 2, 2, BUILDING_HOME, info);
}

bool UsrAI::findCoastalPositionNearCenter(int& x, int& y, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions) {
    this->DebugText("正在搜索市政中心附近的沿海位置...");
    const int MAX_RADIUS = 8;

    for (int r = 1; r <= MAX_RADIUS; r++) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (abs(i) != r && abs(j) != r) continue;

                int checkX = center_x + i;
                int checkY = center_y + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) {
                    continue;
                }

                if (excludedPositions.count({checkX, checkY})) {
                    continue;
                }

                if (this->isPositionValidForBuilding(checkX, checkY, 2, 2, BUILDING_DOCK, info)) {
                    if (this->isPositionReachable(checkX, checkY, info)) {
                        this->DebugText("找到市政中心附近的船坞位置: (" + to_string(checkX) + "," + to_string(checkY) + ")");
                        x = checkX;
                        y = checkY;
                        return true;
                    } else {
                        this->DebugText("船坞位置 (" + to_string(checkX) + "," + to_string(checkY) + ") 靠近市政中心有效但村民无法到达。");
                    }
                }
            }
        }
    }

    this->DebugText("未找到市政中心附近合适的船坞位置。");
    return false;
}


void UsrAI::initializeFishPositions(const tagInfo& info) {
    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_FISH) {
            fishPositions.push_back({res.BlockDR, res.BlockUR});
            this->DebugText("发现鱼资源点: (" + to_string(res.BlockDR) + "," + to_string(res.BlockUR) + ")");
        }
    }
    std::sort(fishPositions.begin(), fishPositions.end(), [&](const std::pair<int, int>& a, const std::pair<int, int>& b) {
        int distA = abs(a.first - center_x) + abs(a.second - center_y);
        int distB = abs(b.first - center_x) + abs(b.second - center_y);
        return distA < distB;
    });
    this->DebugText("鱼资源点已按距市政中心距离排序。");
    fishPositionsInitialized = true;
}

bool UsrAI::isDockNearFish(const std::pair<int, int>& fishPos, const tagInfo& info) {
    const int DOCK_NEAR_FISH_RADIUS = 5;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK) {
            int minDist = INT_MAX;
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    int dockCornerX = b.BlockDR + i;
                    int dockCornerY = b.BlockUR + j;
                    int dist = abs(dockCornerX - fishPos.first) + abs(dockCornerY - fishPos.second);
                    if (dist < minDist) {
                        minDist = dist;
                    }
                }
            }
            if (minDist <= DOCK_NEAR_FISH_RADIUS) {
                this->DebugText("船坞 SN " + to_string(b.SN) + " 位于 (" + to_string(b.BlockDR) + "," + to_string(b.BlockUR) + ") 靠近鱼点 (" + to_string(fishPos.first) + "," + to_string(fishPos.second) + ")。距离: " + to_string(minDist));
                return true;
            }
        }
    }
    return false;
}

bool UsrAI::findDockPositionNearFish(int& x, int& y, const std::pair<int, int>& targetFishPos, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions) {
    this->DebugText("开始搜索特定鱼资源点附近的船坞位置: (" + to_string(targetFishPos.first) + "," + to_string(targetFishPos.second) + ")");

    const int LAND_SEARCH_RADIUS_AROUND_FISH = 5;

    int fishX = targetFishPos.first;
    int fishY = targetFishPos.second;

    for (int dx_land = -LAND_SEARCH_RADIUS_AROUND_FISH; dx_land <= LAND_SEARCH_RADIUS_AROUND_FISH; ++dx_land) {
        for (int dy_land = -LAND_SEARCH_RADIUS_AROUND_FISH; dy_land <= LAND_SEARCH_RADIUS_AROUND_FISH; ++dy_land) {
            int landX = fishX + dx_land;
            int landY = fishY + dy_land;

            if (landX < 0 || landY < 0 || landX >= 128 || landY >= 128) {
                continue;
            }

            if (!this->isLand((*info.theMap)[landX][landY].type)) {
                continue;
            }
            this->DebugText("  在鱼点附近找到陆地单元格: (" + to_string(landX) + "," + to_string(landY) + ")");

            for (int dockOffsetX = -1; dockOffsetX <= 1; ++dockOffsetX) {
                for (int dockOffsetY = -1; dockOffsetY <= 1; ++dockOffsetY) {
                    int dockCandidateX = landX + dockOffsetX;
                    int dockCandidateY = landY + dockOffsetY;

                    if (excludedPositions.count({dockCandidateX, dockCandidateY})) {
                        continue;
                    }

                    if (this->isTooCloseToExistingDocks(dockCandidateX, dockCandidateY, info)) {
                        continue;
                    }

                    if (this->isPositionValidForBuilding(dockCandidateX, dockCandidateY, 2, 2, BUILDING_DOCK, info)) {
                        if (this->isPositionReachable(dockCandidateX, dockCandidateY, info)) {
                            this->DebugText("找到有效的船坞位置: (" + to_string(dockCandidateX) + "," + to_string(dockCandidateY) + ") 靠近鱼点 (" + to_string(fishX) + "," + to_string(fishY) + ") 且与陆地相邻 (" + to_string(landX) + "," + to_string(landY) + ")");
                            x = dockCandidateX;
                            y = dockCandidateY;
                            return true;
                        } else {
                            this->DebugText("船坞位置 (" + to_string(dockCandidateX) + "," + to_string(dockCandidateY) + ") 靠近鱼点有效但村民无法到达。");
                        }
                    }
                }
            }
        }
    }
    this->DebugText("未找到特定鱼资源点附近的合适船坞位置: (" + to_string(targetFishPos.first) + "," + to_string(targetFishPos.second) + ")");
    return false;
}


void UsrAI::assignTasksToVillagers(const tagInfo& info) {
    this->DebugText("警告: 直接调用 assignTasksToVillagers。请考虑使用 assignTasksToVillagersWithLimits。");

    int woodWorkers = 0;
    int foodWorkers = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort != 0) continue;
        if (farmer.NowState == HUMAN_STATE_WORKING) {
            for (const auto& res : info.resources) {
                if (res.SN == farmer.WorkObjectSN) {
                    if (res.Type == RESOURCE_TREE) woodWorkers++;
                    else if (res.Type == RESOURCE_GAZELLE || res.Type == RESOURCE_ELEPHANT || res.Type == RESOURCE_FISH) foodWorkers++;
                    break;
                }
            }
        }
    }

    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort != 0 || farmer.NowState != HUMAN_STATE_IDLE) continue;

        if (foodWorkers < 3) {
            std::unordered_set<int> emptyExcludedSet;
            int targetFoodSN = this->findNearestResource(farmer, RESOURCE_GAZELLE, info, emptyExcludedSet);
            if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(farmer, RESOURCE_ELEPHANT, info, emptyExcludedSet);
            if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(farmer, RESOURCE_FISH, info, emptyExcludedSet);
            if (targetFoodSN != -1) {
                if (HumanAction(farmer.SN, targetFoodSN) > 0) {
                    this->DebugText("村民 #" + to_string(farmer.SN) + " 被指派收集食物 (确保至少3名)");
                    foodWorkers++;
                    continue;
                }
            }
        }

        if (woodWorkers < 10) {
            std::unordered_set<int> emptyExcludedSet;
            int targetTreeSN = this->findNearestResource(farmer, RESOURCE_TREE, info, emptyExcludedSet);
            if (targetTreeSN != -1) {
                if (HumanAction(farmer.SN, targetTreeSN) > 0) {
                    this->DebugText("村民 #" + to_string(farmer.SN) + " 被指派砍伐木材");
                    woodWorkers++;
                    continue;
                }
            }
        }

        if (foodWorkers < 5) {
            std::unordered_set<int> emptyExcludedSet;
            int targetFoodSN = this->findNearestResource(farmer, RESOURCE_GAZELLE, info, emptyExcludedSet);
            if (targetFoodSN == -1) {
                targetFoodSN = this->findNearestResource(farmer, RESOURCE_ELEPHANT, info, emptyExcludedSet);
            }
            if (targetFoodSN == -1) {
                targetFoodSN = this->findNearestResource(farmer, RESOURCE_FISH, info, emptyExcludedSet);
            }

            if (targetFoodSN != -1) {
                if (HumanAction(farmer.SN, targetFoodSN) > 0) {
                    this->DebugText("村民 #" + to_string(farmer.SN) + " 被指派收集更多食物");
                    foodWorkers++;
                }
            }
        }
    }
}


void UsrAI::assignTasksToVillagersWithLimits(const tagInfo& info, bool reserveOneIdleForDock) {
    for (auto it = ordinaryVillagers.begin(); it != ordinaryVillagers.end(); ) {
        bool exists = false;
        for (const auto& farmer : info.farmers) {
            if (farmer.SN == *it) {
                exists = true;
                break;
            }
        }
        if (!exists) {
            this->DebugText("从普通村民集合中移除死亡村民 #" + to_string(*it) + "。");
            it = ordinaryVillagers.erase(it);
        }
        else {
            ++it;
        }
    }

    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort != 0) continue;
        if ((farmer.SN == houseBuilderSN && !dockBuilderReserved && currentStage == STAGE_BUILD_HOUSES) || (farmer.SN == dockBuilderSN && dockBuilderReserved)) {
            continue;
        }

        if (ordinaryVillagers.find(farmer.SN) == ordinaryVillagers.end()) {
            ordinaryVillagers.insert(farmer.SN);
            this->DebugText("新村民 #" + to_string(farmer.SN) + " 已添加到普通村民集合。");
        }
    }

    int woodWorkers = 0;
    int foodWorkers = 0;
    int buildWorkers = 0;
    int idleCount = 0;

    for (const auto& farmer : info.farmers) {
        if (ordinaryVillagers.count(farmer.SN) == 0) {
            continue;
        }

        if (farmer.NowState == HUMAN_STATE_IDLE) {
            idleCount++;
        } else if (farmer.NowState == HUMAN_STATE_WORKING) {
            for (const auto& res : info.resources) {
                if (res.SN == farmer.WorkObjectSN) {
                    if (res.Type == RESOURCE_TREE) {
                        woodWorkers++;
                    } else if (res.Type == RESOURCE_GAZELLE ||
                               res.Type == RESOURCE_ELEPHANT ||
                               res.Type == RESOURCE_FISH) {
                        foodWorkers++;
                    }
                    break;
                }
            }
        } else if (farmer.NowState == HUMAN_STATE_WALKING) {
            bool isBuildingTarget = false;
            for (const auto& b : info.buildings) {
                if (b.Percent < 100 &&
                    (int)(farmer.DR0 / BLOCKSIDELENGTH) >= b.BlockDR &&
                    (int)(farmer.DR0 / BLOCKSIDELENGTH) < (b.BlockDR + (b.Type == BUILDING_DOCK ? 2 : (b.Type == BUILDING_STOCK ? 3 : 2))) &&
                    (int)(farmer.UR0 / BLOCKSIDELENGTH) >= b.BlockUR &&
                    (int)(farmer.UR0 / BLOCKSIDELENGTH) < (b.BlockUR + (b.Type == BUILDING_DOCK ? 2 : (b.Type == BUILDING_STOCK ? 3 : 2)))) {
                    isBuildingTarget = true;
                    break;
                }
            }
            if (isBuildingTarget) {
                buildWorkers++;
            }
        }
    }

    this->DebugText("普通村民任务统计: 空闲=" + to_string(idleCount) +
              " 木材=" + to_string(woodWorkers) +
              " 食物=" + to_string(foodWorkers) +
              " 建造=" + to_string(buildWorkers));

    std::vector<const tagFarmer*> availableIdleFarmers;
    for (const auto& farmer : info.farmers) {
        if (ordinaryVillagers.count(farmer.SN) && farmer.NowState == HUMAN_STATE_IDLE) {
            availableIdleFarmers.push_back(&farmer);
        }
    }

    std::sort(availableIdleFarmers.begin(), availableIdleFarmers.end(), [&](const tagFarmer* a, const tagFarmer* b) {
        int distA = abs(a->BlockDR - center_x) + abs(a->BlockUR - center_y);
        int distB = abs(b->BlockDR - center_x) + abs(b->BlockUR - center_y);
        return distB < distA;
    });

    for (const tagFarmer* farmer_ptr : availableIdleFarmers) {
        const tagFarmer& current_farmer = *farmer_ptr;
        bool assignedThisTurn = false;
        std::unordered_set<int> villagerExcludedResources;

        if (foodWorkers < 3) {
            int targetFoodSN = -1;
            while (!assignedThisTurn) {
                targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_GAZELLE, info, villagerExcludedResources);
                if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_ELEPHANT, info, villagerExcludedResources);
                if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_FISH, info, villagerExcludedResources);

                if (targetFoodSN != -1) {
                    int ret = HumanAction(farmer_ptr->SN, targetFoodSN);
                    if (ret > 0) {
                        this->DebugText("村民 #" + to_string(farmer_ptr->SN) + " 被指派收集食物。");
                        foodWorkers++;
                        assignedThisTurn = true;
                    } else {
                        villagerExcludedResources.insert(targetFoodSN);
                        this->DebugText("村民 #" + to_string(farmer_ptr->SN) + " 无法到达食物资源 SN " + to_string(targetFoodSN) + "。尝试其他食物资源。");
                    }
                } else {
                    break;
                }
            }
        }

        if (assignedThisTurn) continue;

        int targetTreeSN = -1;
        while (!assignedThisTurn) {
            targetTreeSN = this->findNearestResource(current_farmer, RESOURCE_TREE, info, villagerExcludedResources);
            if (targetTreeSN != -1) {
                int ret = HumanAction(farmer_ptr->SN, targetTreeSN);
                if (ret > 0) {
                    this->DebugText("村民 #" + to_string(farmer_ptr->SN) + " 被指派砍伐木材。");
                    woodWorkers++;
                    assignedThisTurn = true;
                } else {
                    villagerExcludedResources.insert(targetTreeSN);
                    this->DebugText("村民 #" + to_string(farmer_ptr->SN) + " 无法到达木材资源 SN " + to_string(targetTreeSN) + "。尝试其他木材资源。");
                }
            } else {
                break;
            }
        }
    }
}


void UsrAI::collectResourcesPhase(const tagInfo& info) {
    this->DebugText("资源收集阶段 | 木材: " + to_string(info.Wood) +
              " | 食物: " + to_string(info.Meat) +
              " | 村民: " + to_string(info.farmers.size()));

    int currentStockCount = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) {
            currentStockCount++;
        }
    }
    this->DebugText("仓库数量: " + to_string(currentStockCount));

    if (!fishPositionsInitialized) {
        this->initializeFishPositions(info);
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
}


void UsrAI::populationGrowthPhase(const tagInfo& info) {
    int currentPopulation = info.farmers.size() + info.armies.size();
    int populationCapacity = info.Human_MaxNum;

    string status = "人口增长阶段 | ";
    status += "当前: " + to_string(currentPopulation) + "/" + to_string(populationCapacity);
    status += " | 目标: " + to_string(targetPopulation);
    this->DebugText(status);

    this->DebugText("人口增长阶段: 尝试生产村民。");
    this->produceVillagers(info);

    if (currentPopulation >= targetPopulation && houseCount == TARGET_HOUSES && housesUnderConstruction == 0) {
        this->DebugText("=== 人口目标已达到且所有房屋已建成，进入所需建筑阶段 ===");
        currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;

        if (houseBuilderSN != -1 && dockBuilderSN == -1) {
            dockBuilderSN = houseBuilderSN;
            dockBuilderReserved = true;
            this->DebugText("指派村民 #" + to_string(dockBuilderSN) + " 为船坞建造者 (所有房屋建成后)。");
            if (ordinaryVillagers.count(dockBuilderSN)) {
                ordinaryVillagers.erase(dockBuilderSN);
                this->DebugText("从普通村民集合中移除船坞建造者 #" + to_string(dockBuilderSN) + "。");
            }
        }
        return;
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
}

void UsrAI::buildRequiredBuildingsPhase(const tagInfo& info) {
    this->DebugText("所需建筑阶段 | 仓库: " + string(stockBuilt ? "已完成" : "待定") +
              " | 现有船坞总数: " + to_string(totalDocksPresent) +
              " | 已完成船坞: " + to_string(completedDocksCount) +
              " | 目标船坞: " + to_string(TARGET_DOCKS_NUM));

    int docksUnderConstruction = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK && b.Percent < 100) {
            docksUnderConstruction++;
        }
    }
    this->DebugText("正在建造的船坞: " + to_string(docksUnderConstruction));

    if (completedDocksCount >= TARGET_DOCKS_NUM) {
        currentStage = STAGE_BUILD_FISHING_BOAT;
        this->DebugText("=== 所有目标船坞已建成，进入渔船生产阶段 ===");
        if (dockBuilderSN != -1 && ordinaryVillagers.find(dockBuilderSN) == ordinaryVillagers.end()) {
            ordinaryVillagers.insert(dockBuilderSN);
            dockBuilderReserved = false;
            this->DebugText("船坞建造者 #" + to_string(dockBuilderSN) + " 已释放并添加到普通村民集合。");
        }
        return;
    }

    this->DebugText("buildRequiredBuildingsPhase: 评估船坞建造。船坞已建成: " + to_string(dockBuilt) +
              ", 船坞建造已开始: " + to_string(dockConstructionStarted) +
              ", 船坞建造者已预留: " + to_string(dockBuilderReserved) +
              ", 木材: " + to_string(info.Wood) + ", 所需: " + to_string(BUILD_DOCK_WOOD));

    if (completedDocksCount < TARGET_DOCKS_NUM && docksUnderConstruction == 0) {
        tagFarmer* builderFarmer = nullptr;

        if (dockBuilderSN != -1) {
            for (const auto& farmer : info.farmers) {
                if (farmer.SN == dockBuilderSN && farmer.FarmerSort == 0) {
                    builderFarmer = const_cast<tagFarmer*>(&farmer);
                    this->DebugText("buildRequiredBuildingsPhase: 找到指定的船坞建造者村民 #" + to_string(builderFarmer->SN));
                    break;
                }
            }
        }

        if (builderFarmer == nullptr && dockBuilderSN != -1) {
            bool isBuilderBusy = false;
            for (const auto& farmer : info.farmers) {
                if (farmer.SN == dockBuilderSN &&
                    farmer.NowState != HUMAN_STATE_IDLE) {
                    isBuilderBusy = true;
                    break;
                }
                if (farmer.SN == dockBuilderSN && farmer.NowState == HUMAN_STATE_IDLE) {
                    this->DebugText("指定的船坞建造者 #" + to_string(dockBuilderSN) + " 空闲但未被选中。正在重置。");
                    dockBuilderSN = -1;
                    dockBuilderReserved = false;
                    break;
                }
            }

            if (!isBuilderBusy && dockBuilderSN != -1) {
                 this->DebugText("指定的船坞建造者 #" + to_string(dockBuilderSN) + " 未找到或已死亡。正在重置。");
                 dockBuilderSN = -1;
                 dockBuilderReserved = false;
            } else if (isBuilderBusy) {
                this->DebugText("指定的船坞建造者 #" + to_string(dockBuilderSN) + " 仍在忙碌。等待其空闲。");
            }
        }

        if (builderFarmer == nullptr && dockBuilderSN == -1) {
             for (const auto& farmer : info.farmers) {
                if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                    if (farmer.SN == houseBuilderSN && !dockBuilderReserved) {
                        continue;
                    }
                    builderFarmer = const_cast<tagFarmer*>(&farmer);
                    dockBuilderSN = farmer.SN;
                    dockBuilderReserved = true;
                    ordinaryVillagers.erase(dockBuilderSN);
                    this->DebugText("buildRequiredBuildingsPhase: 重新指派村民 #" + to_string(builderFarmer->SN) + " 为船坞建造者。");
                    break;
                }
            }
        }

        if (builderFarmer != nullptr) {
            int dockX = -1, dockY = -1;
            std::set<std::pair<int, int>> failedDockAttemptsThisCall;
            bool positionFound = false;
            bool shouldBreakLoop = false;

            for (const auto& fishPos : fishPositions) {
                if (this->isDockNearFish(fishPos, info)) {
                    this->DebugText("跳过鱼点 (" + to_string(fishPos.first) + "," + to_string(fishPos.second) + ")，因为附近已有船坞。");
                    continue;
                }

                positionFound = this->findDockPositionNearFish(dockX, dockY, fishPos, info, failedDockAttemptsThisCall);
                if (positionFound) {
                    this->DebugText("找到鱼点附近的新船坞位置: (" + to_string(dockX) + "," + to_string(dockY) + ")");
                    if (info.Wood >= BUILD_DOCK_WOOD) {
                        this->DebugText("buildRequiredBuildingsPhase: 找到船坞建造位置 (" + to_string(dockX) + "," + to_string(dockY) + ")，尝试建造。");
                        int ret = HumanBuild(builderFarmer->SN, BUILDING_DOCK, dockX, dockY);
                        if (ret > 0) {
                            this->DebugText("村民 #" + to_string(builderFarmer->SN) + " 船坞建造命令成功发出。");
                            dockConstructionStarted = true;
                            for (int i = 0; i < 2; i++) {
                                for (int j = 0; j < 2; j++) {
                                    occupiedPositions.insert({dockX+i, dockY+j});
                                }
                            }
                            return;
                        } else {
                            this->DebugText("村民 #" + to_string(builderFarmer->SN) + " 船坞建造命令失败，错误码: " + to_string(ret));
                            if (ret == ACTION_INVALID_HUMANBUILD_OVERLAP || ret == ACTION_INVALID_POSITION_NOT_FIT) {
                                failedDockAttemptsThisCall.insert({dockX, dockY});
                                this->DebugText("位置 (" + to_string(dockX) + "," + to_string(dockY) + ") 已添加到排除列表，尝试新位置。");
                            } else {
                                this->DebugText("非位置相关错误，无法在当前帧解决。");
                                shouldBreakLoop = true;
                                break;
                            }
                        }
                    } else {
                        this->DebugText("木材不足，建造船坞需要 " + to_string(BUILD_DOCK_WOOD) + " 木材。");
                        shouldBreakLoop = true;
                        break;
                    }
                }
                if (shouldBreakLoop) break;
            }

            if (!positionFound && !shouldBreakLoop) {
                this->DebugText("buildRequiredBuildingsPhase: 未在任何鱼资源点附近找到合适的船坞建造位置。");
            }
        } else {
            this->DebugText("buildRequiredBuildingsPhase: 没有空闲村民可用于建造船坞 (或指定村民正在忙碌)。");
        }
    }

    this->DebugText("buildRequiredBuildingsPhase: 评估仓库建造。仓库已建成: " + to_string(stockBuilt) +
              " | 已完成船坞: " + to_string(completedDocksCount) +
              " | 目标船坞: " + to_string(TARGET_DOCKS_NUM) +
              " | 木材: " + to_string(info.Wood) + ", 所需: " + to_string(BUILD_STOCK_WOOD));
    if (!stockBuilt && completedDocksCount >= TARGET_DOCKS_NUM) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info)) {
            if (info.Wood >= BUILD_STOCK_WOOD) {
                tagFarmer* builderForStock = nullptr;
                for (const auto& farmer : info.farmers) {
                    if (ordinaryVillagers.count(farmer.SN) && farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        builderForStock = const_cast<tagFarmer*>(&farmer);
                        break;
                    }
                }

                if (builderForStock != nullptr) {
                    this->DebugText("buildRequiredBuildingsPhase: 找到空闲的普通村民 #" + to_string(builderForStock->SN) + " 尝试建造仓库。");
                    int ret = HumanBuild(builderForStock->SN, BUILDING_STOCK, buildX, buildY);
                    if (ret > 0) {
                        this->DebugText("村民 #" + to_string(builderForStock->SN) + " 正在建造仓库，位置: (" +
                                  to_string(buildX) + "," + to_string(buildY) + ")");

                        for (int i = 0; i < 3; i++) {
                            for (int j = 0; j < 3; j++) {
                                occupiedPositions.insert({buildX+i, buildY+j});
                            }
                        }
                    } else {
                        this->DebugText("村民 #" + to_string(builderForStock->SN) + " 仓库建造命令失败，错误码: " + to_string(ret));
                    }
                } else {
                    this->DebugText("没有空闲的普通村民可用于建造仓库。");
                }
            } else {
                this->DebugText("木材不足，建造仓库需要 " + to_string(BUILD_STOCK_WOOD) + " 木材。");
            }
        }
    }
    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
}

void UsrAI::upgradeAgePhase(const tagInfo& info) {
    this->DebugText("--- 进入时代升级阶段 ---");
    this->DebugText("当前文明时代: " + to_string(info.civilizationStage));

    if (info.civilizationStage == CIVILIZATION_TOOLAGE) {
        ageUpgraded = true;
        if (fishingBoatCount < TARGET_FISHING_BOATS) {
            currentStage = STAGE_BUILD_FISHING_BOAT;
            this->DebugText("=== 时代升级完成，进入渔船生产阶段 ===");
        } else {
            this->DebugText("=== 时代升级完成，渔船目标也已达成。所有任务完成 ===");
        }
        return;
    }

    this->DebugText("时代升级阶段 | 需要 500 食物。当前食物: " + to_string(info.Meat));

    if (info.Meat >= 500) {
        bool townCenterFound = false;
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER) {
                townCenterFound = true;
                this->DebugText("找到市政中心 SN: " + to_string(building.SN) + ", 完成度: " + to_string(building.Percent) + "%, 当前项目: " + to_string(building.Project));
                if (building.Percent == 100 && building.Project == 0) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_UPGRADE);
                    if (ret > 0) {
                        this->DebugText("市政中心开始时代升级。");
                    } else {
                        this->DebugText("市政中心时代升级命令失败，错误码: " + to_string(ret));
                    }
                    break;
                } else if (building.Percent < 100) {
                    this->DebugText("市政中心尚未完全建成，无法升级时代。");
                } else if (building.Project != 0) {
                    this->DebugText("市政中心正在忙碌，无法升级时代。");
                }
            }
        }
        if (!townCenterFound) {
            this->DebugText("未找到市政中心，无法升级时代。");
        }
    } else {
        this->DebugText("食物不足，升级时代需要 500 食物。");
    }
    this->assignTasksToVillagersWithLimits(info, false);
}

void UsrAI::buildFishingBoatPhase(const tagInfo& info) {
    fishingBoatCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2) {
            fishingBoatCount++;
        }
    }

    this->DebugText("渔船生产阶段 | 当前渔船总数: " + to_string(fishingBoatCount) + " | 目标: " + to_string(TARGET_FISHING_BOATS));

    if (fishingBoatCount >= TARGET_FISHING_BOATS) {
        fishingBoatBuilt = true;
        this->DebugText("=== 已达到目标渔船总数。所有渔船生产任务完成 ===");
        if (stockBuilt) {
            currentStage = STAGE_UPGRADE_AGE;
            this->DebugText("=== 渔船舰队已建成且仓库已完成，进入时代升级阶段 ===");
        } else {
            currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;
            this->DebugText("=== 渔船舰队已建成，但仓库未完成，返回所需建筑阶段 ===");
        }
        return;
    }

    bool productionAttemptedThisFrame = false;
    bool anyDockAvailableForProduction = false;
    bool allCompletedDocksAtCapacity = true;

    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100) {
            anyDockAvailableForProduction = true;

            int boatsProducedByThisDock = dockFishingBoatCount[building.SN];

            this->DebugText("  船坞 SN " + to_string(building.SN) + " 已生产渔船: " + to_string(boatsProducedByThisDock) + " | 目标: " + to_string(TARGET_BOATS_PER_DOCK));

            if (boatsProducedByThisDock < TARGET_BOATS_PER_DOCK) {
                allCompletedDocksAtCapacity = false;
                if (building.Project == 0 && info.Wood >= BUILDING_DOCK_CREATE_SAILING_WOOD) {
                    this->DebugText("  船坞 SN " + to_string(building.SN) + " 尝试生产渔船...");
                    int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_SAILING);
                    productionAttemptedThisFrame = true;

                    if (ret > 0) {
                        this->DebugText("  船坞 SN " + to_string(building.SN) + " 开始生产渔船成功。");
                        dockFishingBoatCount[building.SN]++;
                        return;
                    } else {
                        this->DebugText("  从船坞 SN " + to_string(building.SN) + " 生产渔船失败，错误码: " + to_string(ret));
                    }
                } else {
                    if (building.Project != 0) {
                        this->DebugText("  船坞 SN " + to_string(building.SN) + " 正在忙碌，无法生产渔船。");
                    } else if (info.Wood < BUILDING_DOCK_CREATE_SAILING_WOOD) {
                        this->DebugText("  木材不足以生产渔船 (船坞 SN " + to_string(building.SN) + ")。需要: " + to_string(BUILDING_DOCK_CREATE_SAILING_WOOD) + ", 现有: " + to_string(info.Wood));
                    }
                }
            } else {
                this->DebugText("  船坞 SN " + to_string(building.SN) + " 已达到其渔船生产目标 (" + to_string(TARGET_BOATS_PER_DOCK) + "艘)。");
            }
        }
    }

    if (!productionAttemptedThisFrame && fishingBoatCount < TARGET_FISHING_BOATS && allCompletedDocksAtCapacity && completedDocksCount < TARGET_DOCKS_NUM) {
        this->DebugText("=== 现有船坞已达到生产上限，但总渔船数量未达标，返回所需建筑阶段建造更多船坞 ===");
        currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;
        return;
    }


    this->assignTasksToVillagersWithLimits(info, false);
}

int UsrAI::findNearestResource(const tagFarmer& farmer, int resourceType, const tagInfo& info, const std::unordered_set<int>& excludedSNs) {
    int nearestSN = -1;
    double minDistance = -1;

    for (const auto& res : info.resources) {
        if (res.Type == resourceType && res.Cnt > 0 && excludedSNs.find(res.SN) == excludedSNs.end()) {
            double distance = abs(farmer.BlockDR - res.BlockDR) + abs(farmer.BlockUR - res.BlockUR);

            if (nearestSN == -1 || distance < minDistance) {
                minDistance = distance;
                nearestSN = res.SN;
            }
        }
    }
    return nearestSN;
}

void UsrAI::produceVillagers(const tagInfo& info) {
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
            if (info.Meat >= 50) {
                if (info.farmers.size() + info.armies.size() < info.Human_MaxNum) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                    if (ret > 0) {
                        this->DebugText("市政中心开始生产村民。");
                        lastVillagerProductionTime = time(nullptr);
                    } else {
                        this->DebugText("村民生产命令失败，错误码: " + to_string(ret));
                    }
                } else {
                    this->DebugText("人口上限已达，无法生产更多村民。");
                }
            } else {
                this->DebugText("食物不足，无法生产村民。");
            }
            break;
        }
    }
}

bool UsrAI::findNearbyPosition(int& x, int& y, const tagInfo& info) {
    int startX = center_x;
    int startY = center_y;

    for (int r = 0; r <= MAX_HOUSE_SEARCH_RADIUS; ++r) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (r > 0 && abs(i) != r && abs(j) != r) continue;

                int checkX = startX + i;
                int checkY = startY + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128)
                    continue;

                if (this->isPositionValidForBuilding(checkX, checkY, 2, 2, BUILDING_HOME, info)) {
                    x = checkX;
                    y = checkY;
                    lastHouseX = x;
                    lastHouseY = y;
                    this->DebugText("找到房屋建造位置: (" + to_string(x) + "," + to_string(y) + ")，距市政中心半径: " + to_string(r));
                    return true;
                }
            }
        }
    }
    this->DebugText("警告: 在市政中心最大半径 (" + to_string(MAX_HOUSE_SEARCH_RADIUS) + ") 内未找到合适的房屋建造位置。");
    return false;
}

void UsrAI::buildHousesPhase(const tagInfo& info) {
    this->DebugText("建造房屋阶段 | 已建房屋: " + to_string(houseCount) +
              " | 建造中: " + to_string(housesUnderConstruction) +
              " | 目标: " + to_string(TARGET_HOUSES));
    this->DebugText("房屋阶段条件检查: 已建房屋 (" + to_string(houseCount) + ") == 目标房屋 (" + to_string(TARGET_HOUSES) + ") && 建造中房屋 (" + to_string(housesUnderConstruction) + ") == 0");

    if (houseCount >= 1) {
        this->produceVillagers(info);
    }

    if (houseCount == TARGET_HOUSES && housesUnderConstruction == 0) {
        if (completedDocksCount < TARGET_DOCKS_NUM && info.Wood >= BUILD_DOCK_WOOD) {
            this->DebugText("=== 所有房屋已建成且木材充足，预先进入所需建筑阶段建造船坞 ===");
            currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;

            if (houseBuilderSN != -1 && dockBuilderSN == -1) {
                dockBuilderSN = houseBuilderSN;
                dockBuilderReserved = true;
                this->DebugText("指派村民 #" + to_string(dockBuilderSN) + " 为船坞建造者 (房屋建成且木材就绪)。");
                if (ordinaryVillagers.count(dockBuilderSN)) {
                    ordinaryVillagers.erase(dockBuilderSN);
                    this->DebugText("从普通村民集合中移除船坞建造者 #" + to_string(dockBuilderSN) + "。");
                }
            }
        } else {
            this->DebugText("=== 所有房屋已建成，进入人口增长阶段 ===");
            currentStage = STAGE_POPULATION_GROWTH;
            targetPopulation = 10;

            if (houseBuilderSN != -1 && dockBuilderSN == -1) {
                dockBuilderSN = houseBuilderSN;
                dockBuilderReserved = true;
                this->DebugText("指派村民 #" + to_string(dockBuilderSN) + " 为船坞建造者 (房屋建成，进入人口增长)。");
                if (ordinaryVillagers.count(dockBuilderSN)) {
                    ordinaryVillagers.erase(dockBuilderSN);
                    this->DebugText("从普通村民集合中移除船坞建造者 #" + to_string(dockBuilderSN) + "。");
                }
            }
        }
        return;
    }

    if (houseCount + housesUnderConstruction < TARGET_HOUSES) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info)) {
            if (info.Wood >= BUILD_HOUSE_WOOD) {
                tagFarmer* builder = nullptr;
                for (const auto& farmer : info.farmers) {
                    if (farmer.SN == houseBuilderSN && farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                        builder = const_cast<tagFarmer*>(&farmer);
                        break;
                    }
                }

                if (builder == nullptr && houseBuilderSN == -1) {
                    for (const auto& farmer : info.farmers) {
                        if (farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                            builder = const_cast<tagFarmer*>(&farmer);
                            houseBuilderSN = farmer.SN;
                            this->DebugText("重新指派村民 #" + to_string(houseBuilderSN) + " 为房屋建造者。");
                            break;
                        }
                    }
                } else if (builder == nullptr && houseBuilderSN != -1) {
                    this->DebugText("指定的房屋建造者村民 #" + to_string(houseBuilderSN) + " 正在忙碌，等待其空闲。");
                }


                if (builder != nullptr) {
                    this->DebugText("尝试在 (" + to_string(buildX) + "," + to_string(buildY) + ") 建造房屋，村民 #" + to_string(builder->SN));
                    int ret = HumanBuild(builder->SN, BUILDING_HOME, buildX, buildY);
                    if (ret > 0) {
                        this->DebugText("村民 #" + to_string(builder->SN) + " 房屋建造命令成功发出。");
                        housesUnderConstruction++;
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                occupiedPositions.insert({buildX+i, buildY+j});
                            }
                        }
                    } else {
                        this->DebugText("村民 #" + to_string(builder->SN) + " 房屋建造命令失败，错误码: " + to_string(ret));
                    }
                } else {
                    this->DebugText("没有空闲村民可用于建造房屋。");
                }
            } else {
                this->DebugText("木材不足，建造房屋需要 " + to_string(BUILD_HOUSE_WOOD) + " 木材。");
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
}

void UsrAI::assignFishingBoatsToFishResources(const tagInfo& info) {
    this->DebugText("分配渔船到渔场资源。");

    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2 && farmer.NowState == HUMAN_STATE_IDLE) {
            this->DebugText("找到空闲渔船 SN: " + to_string(farmer.SN));

            int targetFishSN = -1;
            double minDistance = -1;
            std::unordered_set<int> excludedFishResources;

            for (const auto& resource : info.resources) {
                if (resource.Type == RESOURCE_FISH && resource.Cnt > 0 && excludedFishResources.find(resource.SN) == excludedFishResources.end()) {
                    double distance = abs(farmer.BlockDR - resource.BlockDR) + abs(farmer.BlockUR - resource.BlockUR);

                    if (targetFishSN == -1 || distance < minDistance) {
                        minDistance = distance;
                        targetFishSN = resource.SN;
                    }
                }
            }

            if (targetFishSN != -1) {
                this->DebugText("尝试将渔船 SN " + to_string(farmer.SN) + " 分配到渔场 SN " + to_string(targetFishSN));
                int ret = HumanAction(farmer.SN, targetFishSN);
                if (ret > 0) {
                    this->DebugText("渔船 SN " + to_string(farmer.SN) + " 成功分配到渔场 SN " + to_string(targetFishSN) + "。");
                } else {
                    this->DebugText("渔船 SN " + to_string(farmer.SN) + " 分配到渔场 SN " + to_string(targetFishSN) + " 失败，错误码: " + to_string(ret));
                    excludedFishResources.insert(targetFishSN);
                }
            } else {
                this->DebugText("未找到可用的渔场资源，渔船 SN " + to_string(farmer.SN) + " 保持空闲。");
            }
        }
    }
}


void UsrAI::processData() {
    tagInfo info = getInfo();

    houseCount = 0;
    housesUnderConstruction = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_HOME) {
            if (b.Percent == 100) houseCount++;
            else housesUnderConstruction++;
        }
    }

    stockBuilt = false;
    dockBuilt = false;
    dockConstructionStarted = false;
    totalDocksPresent = 0;
    completedDocksCount = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) {
            stockBuilt = true;
        }
        if (b.Type == BUILDING_DOCK) {
            totalDocksPresent++;
            if (b.Percent == 100) {
                dockBuilt = true;
                completedDocksCount++;
            }
            dockConstructionStarted = true;
        }
    }

    fishingBoatCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2) {
            fishingBoatCount++;
        }
    }


    this->DebugText("当前游戏阶段: " + to_string(currentStage));

    switch(currentStage) {
        case STAGE_INITIAL:
            if (!centerInitialized) this->initializeCenter(info);
            break;

        case STAGE_BUILD_HOUSES:
            this->buildHousesPhase(info);
            break;

        case STAGE_POPULATION_GROWTH:
            this->populationGrowthPhase(info);
            break;

        case STAGE_COLLECT_RESOURCES:
            this->collectResourcesPhase(info);
            break;

        case STAGE_BUILD_REQUIRED_BUILDINGS:
            this->buildRequiredBuildingsPhase(info);
            break;

        case STAGE_UPGRADE_AGE:
            this->upgradeAgePhase(info);
            break;

        case STAGE_BUILD_FISHING_BOAT:
            this->buildFishingBoatPhase(info);
            break;
    }

    this->assignFishingBoatsToFishResources(info);

    prevInfo = info;
}
